﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using ITAP.Core.Modelling.Primitives;
using ITAP.ShprossesBuilder.Calculations;
using ITAP.Core.Calculations;
using ITAP.Core.Modelling;

namespace ITAP.ShprossesBuilder.Modelling.Measurement
{
    public class Dimension : IEquatable<Dimension>, ICloneable
    {
        //private bool isOffset = false;

        //public bool IsOffset
        //{
        //    get { return isOffset; }
        //    set { isOffset = value; }
        //}

        protected DimensionSide side;

        public DimensionSide Side
        {
            get { return side; }
            set { side = value; }
        }
        protected int level;

        public int Level
        {
            get { return level; }
            set { level = value; }
        }

        public virtual string Text
        {
            get
            {
                return primitive.Length.ToString("0.0");
            }
        }

        protected IEndedPrimitive primitive;

        public IEndedPrimitive Primitive
        {
            get { return primitive; }
            set { primitive = value; }
        }

        public virtual void AcceptVisitor(IDimensionVisitor visitor)
        {
            visitor.Visit(this);
        }


        public Dimension(IEndedPrimitive primitive)
        {
            this.primitive = (IEndedPrimitive)primitive.Clone();
        }


        #region IEquatable<Dimension> Members

        public virtual bool Equals(Dimension other)
        {
            if (this.primitive.Equals(other.Primitive))
                return true;
            else
                return false;
        }

        #endregion

        public override int GetHashCode()
        {
            return 1;
            ModelPoint[] sort = ModelCalculations.SortPointsByDistance(new ModelPoint(0, 0), this.primitive.StartPoint, this.primitive.EndPoint);
            string hashString = ((int)(sort[0].X + sort[0].Y + sort[1].X + sort[1].Y)).ToString();
            //string hashString = sort[0].X.ToString() + sort[0].Y.ToString() + sort[1].X.ToString() + sort[1].Y.ToString();
            return hashString.GetHashCode();
        }

        public virtual bool IsOverlap(Dimension other)
        {
            if (other.Side == DimensionSide.Auto && this.Level == other.Level)
            {
                if (this.Primitive.GetType() == other.Primitive.GetType())
                {
                    ModelCalculations.PrimitivesIntersectionType intersectionType = ModelCalculations.GetPrimitivesIntersectionType(this.Primitive, other.Primitive, 0.0001);
                    if (intersectionType == ModelCalculations.PrimitivesIntersectionType.OverlapOrCollide)
                    {
                        if (this.Primitive.IsPointInSegment(other.Primitive.StartPoint, false) ||
                            this.Primitive.IsPointInSegment(other.Primitive.EndPoint, false))
                            return true;
                        else
                            return false;
                    }
                    else
                        return false;
                }
                else
                    return false;
                //ModelPoint[] points = other.Primitive.IntersectMainLines(this.Primitive, EndType.Start);

                //if (points[0] != null && (double.IsInfinity(points[0].X) || double.IsInfinity(points[0].Y) ||
                //    double.IsNaN(points[0].X) || double.IsNaN(points[0].Y)))
                //{
                //    if (this.Primitive.IsPointInSegment(other.Primitive.StartPoint, false) ||
                //        this.Primitive.IsPointInSegment(other.Primitive.EndPoint, false))
                //        return true;
                //    else
                //        return false;
                //}
                //else
                //    return false;
            }
            else
            {
                if (//(this.Side == other.Side) &&
                    this.Level == other.Level &&
                   (this.Primitive.IsPointInSegment(other.Primitive.StartPoint, false) ||
                    this.Primitive.IsPointInSegment(other.Primitive.EndPoint, false)))
                    return true;
                else
                    return false;
            }
        }

        /// <summary>
        /// Проверка, вмещает ли целиком данный размер другой.
        /// </summary>
        /// <param name="other"></param>
        /// <returns></returns>
        public virtual bool IsCollide(Dimension other)
        {
            if (this.Side == DimensionSide.Auto && this.Level == other.Level)
            {
                if (this.Primitive.GetType() != other.Primitive.GetType())
                    return false;

                ModelCalculations.PrimitivesIntersectionType intersectionType = ModelCalculations.GetPrimitivesIntersectionType(this.Primitive, other.Primitive, 0.0001);
                if (intersectionType == ModelCalculations.PrimitivesIntersectionType.OverlapOrCollide)
                {
                    if (this.Primitive.IsPointInSegment(other.Primitive.StartPoint, true) &&
                        this.Primitive.IsPointInSegment(other.Primitive.EndPoint, true))
                        return true;
                    else
                        return false;
                }
                //else if (intersectionType == ModelCalculations.PrimitivesIntersectionType.Parallel)
                //{
                //    if (SimpleEqualProvider.IsEqual(this.Primitive.StartPoint.Y, other.Primitive.EndPoint.Y, 0.00001) &&
                //       SimpleEqualProvider.IsEqual(this.Primitive.Length, other.Primitive.Length, 0.00001))
                //        return true;
                //    else
                //        return false;
                //}
                else
                    return false;
            }
            else
            {
                if (this.Level == other.Level &&
                   (this.Primitive.IsPointInSegment(other.Primitive.StartPoint, true) &&
                    this.Primitive.IsPointInSegment(other.Primitive.EndPoint, true)))
                    return true;
                else
                {
                    return false;
                    //ModelCalculations.PrimitivesIntersectionType intersectionType = 
                    //    ModelCalculations.GetPrimitivesIntersectionType(this.Primitive, other.Primitive, 0.0001);
                    //if (intersectionType == ModelCalculations.PrimitivesIntersectionType.Parallel)
                    //{
                    //    if (SimpleEqualProvider.IsEqual(this.Primitive.StartPoint.Y, other.Primitive.EndPoint.Y, 0.00001) &&
                    //       SimpleEqualProvider.IsEqual(this.Primitive.Length, other.Primitive.Length, 0.00001))
                    //        return true;
                    //    else
                    //        return false;
                    //}
                    //else
                    //    return false;
                }
            }
        }

        #region ICloneable Members

        public virtual object Clone()
        {
            Dimension clone = new Dimension((IEndedPrimitive)this.Primitive.Clone());
            clone.Level = this.level;
            clone.side = this.side;
            return clone;

        }

        #endregion
    }

    public class DimensionEqualityComparer : IEqualityComparer<Dimension>
    {

        #region IEqualityComparer<Dimension> Members

        public bool Equals(Dimension x, Dimension y)
        {
            if (x.Primitive.Equals(y.Primitive))
                return true;
            else
            {
                ModelCalculations.PrimitivesIntersectionType intersectionType =
                    ModelCalculations.GetPrimitivesIntersectionType(x.Primitive, y.Primitive, 0.0001);
                if (intersectionType == ModelCalculations.PrimitivesIntersectionType.Parallel)
                {
                    if (SimpleEqualProvider.IsEqual(x.Primitive.StartPoint.Y, y.Primitive.EndPoint.Y, 0.001) &&
                       SimpleEqualProvider.IsEqual(x.Primitive.Length, y.Primitive.Length, 0.001))
                        return true;
                    else if (SimpleEqualProvider.IsEqual(x.Primitive.StartPoint.X, y.Primitive.EndPoint.X, 0.001) &&
                       SimpleEqualProvider.IsEqual(x.Primitive.Length, y.Primitive.Length, 0.001))
                        return true;
                    else
                        return false;
                }

                return false;
            }
        }

        public int GetHashCode(Dimension obj)
        {
            return 1;
            int hash = obj.GetHashCode();
            return hash;
        }

        #endregion
    }
}
